﻿@page "/Demo_BlazorSession"
@* for disposing dno *@
@implements IDisposable


<h2>BlazorSession:</h2>
<p class="text-primary text-lg-left font-weight-bolder">
	An unique BlazorSession object is for one Blazor lifetime.
	<br />
	It's the most important service for BlazorPlus components
</p>


@if (BlazorSession.Current.Browser == null)
{
	//wait BlazorSession.Current.Browser ready
	BlazorSession.Current.EvalCodeAsync("console.log('hello?')").ContinueWithSession(delegate
	{
		StateHasChanged();
	});
	return;
}


<style>
	legend {
		font-size: 20px;
		font-weight: bold;
		margin: 0px;
	}

	.mywarningtoast {
		background-color: orange !important;
		color: darkgreen !important;
	}
</style>

<fieldset>
	<legend>Browser Toast:</legend>
	<div>Say something witout clicking OK ,all previous items with same key will be cleared</div>
	<button class='btn btn-info' @onclick='()=>BlazorSession.Current.Toast("Time Is "+DateTime.Now.ToString("HH:mm:ss.fff"),2000)'>Toast</button>
	<button class='btn btn-info' @onclick='()=>BlazorSession.Current.ToastClear()'>ToastClear</button>
	<button class='btn btn-info' @onclick='()=>BlazorSession.Current.Toast("Time Is "+DateTime.Now.ToString("HH:mm:ss.fff"),2000,"mytimetoast")'>Toast With Key</button>
	<button class='btn btn-info' @onclick='()=>BlazorSession.Current.Toast("The action is failed.",2000,"mywarningtoast")'>Key as css class</button>
</fieldset>

@code{
	void DoSetSessionData()
	{
		int sid = BlazorSession.Current.SessionId;
		int num = new Random().Next(1000, 9999);
		BlazorSession.Current["magicnumber"] = num;
		BlazorSession.Current.Alert("SetSessionData", "Session Id is " + sid + ", value " + num + " has been set , try to switch to another tab and back , click Read Session Data");
	}
	void DoReadSessionData()
	{
		int sid = BlazorSession.Current.SessionId;
		int num = 0;
		object objnum = BlazorSession.Current["magicnumber"];
		if (objnum != null)
			num = (int)objnum;
		if (objnum == null)
			BlazorSession.Current.Alert("ReadSessionData", "Session Id is " + sid + ", but value was not setted .");
		else
			BlazorSession.Current.Alert("ReadSessionData", "Session Id is " + sid + ", value was setted to " + num + " ");
	}
	void DoGetSessionDataCount()
	{
		Dictionary<object, object>
			map = BlazorSession.Current.GetItemMap(false);
		if (map == null)
			BlazorSession.Current.Toast("There's no any session data");
		else
			BlazorSession.Current.Toast("Session Data Count : " + map.Count);
	}
}

<br />
<fieldset>
	<legend>Browser Console:</legend>
	<div>open browser console to check the logs</div>
	<button class='btn btn-info' @onclick='()=>BlazorSession.Current.ConsoleLog("Current Date Is",DateTime.Now)'>ConsoleLog</button>

	<button class='btn btn-info' @onclick='()=>BlazorSession.Current.ConsoleInfo("Current Date Is",DateTime.Now)'>ConsoleInfo</button>

	<button class='btn btn-info' @onclick='()=>BlazorSession.Current.ConsoleWarn("Current Date Is",DateTime.Now)'>ConsoleWarn</button>

	<button class='btn btn-info' @onclick='()=>BlazorSession.Current.ConsoleError("Current Date Is",DateTime.Now)'>ConsoleError</button>
</fieldset>

<br />
<fieldset>
	<legend>Browser JavaScript:</legend>
	<div>Interactive with browser script. <a href="/Demo_JavaScript" style="display:none;">More JavaScript Sample</a></div>
	<div>It's not recommanded to use localStorage to store sensitive data in browser</div>
	<button class='btn btn-info' @onclick='DoEvalCode'>EvalCode</button>
	<button class='btn btn-info' @onclick='DoSetLocalStorage'>localStorage.setItem</button>
	<button class='btn btn-info' @onclick='DoGetLocalSotrange'>localStorage.getItem</button>
	<button class='btn btn-info' @onclick='DoTestClientCallback'>Client Callback</button>

</fieldset>

@code{
	void DoEvalCode()
	{
		//use arguments array
		BlazorSession.Current.EvalCode("alert(arguments[0])", "This is argument 0");
	}
	void DoSetLocalStorage()
	{
		//Use InvokeFunction to pass parameters more easily
		BlazorSession.Current.InvokeFunction("localStorage.setItem", "demo-index-value", DateTime.Now.Ticks.ToString());
		BlazorSession.Current.Alert("Done", "demo-index-value has been added to localStorage");
	}

	async void DoGetLocalSotrange()
	{
		string value = await BlazorSession.Current.EvalCodeAsync<string>("console.log('get localStorage'); return localStorage.getItem('demo-index-value')");
		long ticks;
		if (!long.TryParse(value, out ticks))
		{
			BlazorSession.Current.Alert("Error", "You never set the 'demo-index-value'");
		}
		else
		{
			TimeSpan ts = DateTime.Now - new DateTime(ticks);
			BlazorSession.Current.Alert("demo-index-value", "You set 'demo-index-value' " + Math.Ceiling(ts.TotalSeconds) + " seconds ago\r\nReload this page and try again.");
		}
	}

	void DoTestClientCallback()
	{
		if (dno != null)
		{
			BlazorSession.Current.ToastClear();
			BlazorSession.Current.Toast("another job is running");
			return;
		}

		dno = DotNetObjectReference.Create(this);

		BlazorSession.Current.EvalCode(@"
var dno=arguments[0];
console.log(dno);
Toast('wait for 0.8 sec',800);
setTimeout(function(){
dno.invokeMethodAsync('_Index_ClientCallbackHandler','hello world from client side');
},800);
"
		, dno);
	}

	DotNetObjectReference<Demo_BlazorSession> dno;

	void IDisposable.Dispose()
	{
		if (dno != null)
			dno.Dispose();
	}

	[Microsoft.JSInterop.JSInvokable()]
	public void _Index_ClientCallbackHandler(string msg)
	{
		if (dno != null)
		{
			dno.Dispose();
			dno = null;
		}

		BlazorSession.Current.Alert("Result", msg);
	}
}






<br />
<fieldset>
	<legend>Server Session Data In Memory:</legend>
	<div>Use session data to store session scope data, components can community with each other.</div>
	<button class='btn btn-info' @onclick='DoSetSessionData'>Set Session Data</button>
	<button class='btn btn-info' @onclick='DoReadSessionData'>Read Session Data</button>
	<button class='btn btn-info' @onclick='DoGetSessionDataCount'>Get Session Data Count</button>
</fieldset>



<br />
<fieldset>
	<legend>Server Shared Data For Browser:</legend>
	<div>BlazorPlus save a unique key into cookie/sessionStorage/localStorage and help developer to persist data</div>
	<div>The values are persisted for short/long time <span style="color:red;font-weight:bold">after page refreshed</span></div>
	<div>Your browser uid is : @BlazorBrowser.Current.UniqueID</div>
	<button class='btn btn-info' @onclick='DoSetMemoryItem'>Set Memory Data</button>
	<button class='btn btn-info' @onclick='DoGetMemoryItem'>Read Memory Data</button>
	<button class='btn btn-info' @onclick='DoSetStringItemAsync'>Set Persisted String</button>
	<button class='btn btn-info' @onclick='DoGetStringItemAsync'>Get Persisted String</button>
</fieldset>


@code{
	void DoSetMemoryItem()
	{
		//Memory Data will be resetted for 3 cases :
		// 1 - the application restart
		// 2 - user close all blazor pages after 10 minutes (default configuration)
		// 3 - switch browser, use incognito mode , clear the browser storages etc...
		string time = DateTime.Now.ToLongTimeString();
		BlazorBrowser.Current.SetMemoryItem("Time", time);
		BlazorSession.Current.Toast("Value has been setted to '" + time + "'");
	}
	void DoGetMemoryItem()
	{
		BlazorSession.Current.Alert("Time", "Value is '" + BlazorBrowser.Current.GetMemoryItem("Time") + "'");
	}

	async Task DoSetStringItemAsync()
	{
		UIDialogOption option = new UIDialogOption();
		option.Title = "Your message";
		option.Message = "Please type your message to save";
		option.DefaultValue = "Now is " + DateTime.Now.ToLongTimeString();
		string message = await BlazorSession.Current.PromptAsync(option);
		if (string.IsNullOrEmpty(message))
			return;

		//Check the Providers.cs of BlazorPlusDemo
		//by the WebCustomizeSession implementation , the value is storage in BrowserStringItems folder

		await BlazorBrowser.Current.SetStringItemAsync("MyMsg", message);
		BlazorSession.Current.Toast("MyMsg has been saved");
	}
	async Task DoGetStringItemAsync()
	{
		BlazorSession.Current.Alert("MyMsg", "MyMsg loaded : " + await BlazorBrowser.Current.GetStringItemAsync("MyMsg"));
	}
}

<br />
<fieldset>
	<legend>Waiting Mask:</legend>
	<div>If you do a long time action and don't want user click anything, use WatingMask</div>
	<div>You can customize it by : set css style for class .bp_waiting_mask , or override the default JS function GetWaitingMaskHTML or AddWaitingMask/SubWaitingMask</div>
	<button class='btn btn-info' @onclick="ShowWaitingMask">ShowWatingMask</button>

	<button class='btn btn-info' @onclick="TestAsync">TestAsync</button>

	<button class='btn btn-info' @onclick="Test2Async">Test2Async</button>

	<button class='btn btn-info' @onclick="TestSync">TestSync</button>

	@_test_count

</fieldset>

@code{
	void ShowWaitingMask()
	{
		BlazorSession.Current.AddWaitingMask();
		BlazorSession.Current.Toast("Wait for 5 seconds..");
		BlazorSession.Current.SetTimeout(5000, delegate
		{
			BlazorSession.Current.SubWaitingMask();
		});
	}

	int _test_count = 0;

	async Task TestAsync()
	{
		_test_count++;
		await BlazorSession.Current.InvokeInRenderThreadAsync(async delegate
		{
			await Task.Delay(2000);
			_test_count++;
		}, true);//pass true to show the wait-mask
	}

	async Task Test2Async()
	{
		_test_count++;
		await BlazorSession.Current.InvokeInRenderThreadAsync(delegate
		{
			System.Threading.Thread.Sleep(2000);
			_test_count++;
		}, true);//pass true to show the wait-mask
	}

	void TestSync()
	{
		_test_count++;//not able update immediatley , the render thread blocked
		BlazorSession.Current.InvokeInRenderThread(delegate
		{
			System.Threading.Thread.Sleep(2000);//JUST a test , not recommand to block render thread
		_test_count++;
		}, true);//pass true to show the wait-mask
	}

}

<br />
<br />
<br />